#include "CCPacket.h"
//#include "Packet.h"
#include "log.h"
#include "EncryptDecrypt.h"

const uint32 g_encodeflag = (0x01);

extern CMemPool*	_memPool;

NAMESPACE_CC_BY_BEGIN


CCPackete::CCPackete(void) :m_cache(_memPool)
{
    m_bIsEncrypted = 0;
}

CCPackete::~CCPackete(void)
{
}

char *CCPackete::packet_buf(void)    
{ 
	return m_cache.data(); 
}

int CCPackete::packet_size(void)    
{ 
	return m_cache.data_len(); 
}


int CCPackete::parse_protocol(const char* buff)
{
	return (DEFAULT_PROTOCOL);

	PBAHead* phead = (PBAHead*)buff;
    if (DEFAULT_PROTOCOL == PBA_PROTOCOL)
	{
		if (0xFE == phead->m_magic[0] && 0x01 == phead->m_magic[1])
			return PBA_PROTOCOL;
		else
			return NONE_PROTOCOL;
	}


	return NONE_PROTOCOL;
}

int CCPackete::parse_head_len(int protocol)
{
	int len = 0;
    if (PBA_PROTOCOL == protocol)
		len = sizeof(PBAHead);
	return len;
}


bool CCPackete::check_head(const char* data)
{
	int protocol = CCPackete::parse_protocol(data);
    PBAHead* phead = (PBAHead*)data;

    if (PBA_PROTOCOL == protocol)
		return ((0xFE == phead->m_magic[0]) && (0x01 == phead->m_magic[1]));
	return false;
}


int CCPackete::parse_packet_len(const char* data)
{
	int protocol = CCPackete::parse_protocol(data);
    PBAHead* phead = (PBAHead*)data;

    if (PBA_PROTOCOL == protocol)
	    return (sizeof(PBAHead)+ntohl(phead->m_datalen));

	return -1;
}


void CCPackete::_reset(void)
{
	m_protocol = NONE_PROTOCOL;
	m_cache.clear();
	m_nBufPos = 0;
}

void CCPackete::ParseExtData(void)
{
}

void CCPackete::ParseJDExtData(void)
{
	char jd_data[MAX_JD_EXTDATA_LEN];

	int nLen = -1;
	_Read((char*)&nLen, sizeof(int));
	nLen = ntohl(nLen);
	if (nLen < 0)
	{
		return;
	}
	if (nLen > sizeof(jd_data))
	{
		_readundo(sizeof(int));
		return;
	}

	if (_Read(jd_data, nLen))
	{
	}

	return;
}

bool CCPackete::_copy(const void *pInBuf, int nLen)
{
	_reset();
	if (nLen > PACKET_BUFFER_SIZE || nLen <= 0)
	{
		log_error("Fatal Error , nLen:%d",nLen);
		return false;
	}

	m_protocol = parse_protocol((char*)pInBuf);
	if (NONE_PROTOCOL == m_protocol)
	{
		log_error("Fatal Error , parse protocol ERR  nLen:%d", nLen);
		return false;
	}

	m_cache.append((char*)pInBuf, nLen);
	m_nBufPos = GetHeadLength();

	ParseExtData();

	return true;
}

void CCPackete::_begin(uint32 nCmdType, int proto_type)
{
	_reset();
    if (PBA_PROTOCOL == proto_type)
	{
		m_protocol = PBA_PROTOCOL;
		this->writePBAHead(nCmdType);
	}
}

void CCPackete::_begin(unsigned int cmd, unsigned short dsttype, unsigned int dstid, unsigned short srctype, unsigned int srcid, unsigned int seq, int proto_type)
{
	_reset();
	if (PBA_PROTOCOL == proto_type)
	{
		m_protocol = PBA_PROTOCOL;
		writePBAHead(cmd, dsttype, dstid, srctype, srcid, seq, 0);
	}
}

void CCPackete::writePBAHead(unsigned int cmd, unsigned short dsttype, unsigned int dstid, unsigned short srctype, unsigned int srcid, unsigned int seq, unsigned char ver)
{
	PBAHead head;

	
	head.m_ver = ver;
	head.m_cmd = htonl(cmd);
	head.m_dsttype = htons(dsttype);
	head.m_srctype = htons(srctype);
	head.m_dstid = htonl(dstid);
	head.m_srcid = htonl(srcid);
	head.m_seq = htonl(seq);
	head.m_datalen = 0;

	m_cache.append((char*)&head, sizeof(PBAHead));
}

int CCPackete::GetCmdType(void)
{
    PBAHead* phead = (PBAHead*)m_cache.data();

	int cmd = 0;
    if (PBA_PROTOCOL == m_protocol)
		cmd = ntohl(phead->m_cmd);
	return cmd;
}

int CCPackete::GetSubCmdType(void)
{
	return 0;
}

char CCPackete::GetVersion(void)
{
    PBAHead* phead = (PBAHead*)m_cache.data();

	char version = 0;
    if (PBA_PROTOCOL == m_protocol)
		version = phead->m_ver;

	return version;
}

int CCPackete::GetBodyLength(void)
{
    PBAHead* phead = (PBAHead*)m_cache.data();

	int len  = 0;
    if (PBA_PROTOCOL == m_protocol)
		len = (sizeof(PBAHead)+ntohl(phead->m_datalen));

	return len;
}

int CCPackete::GetHeadLength(void)
{
	int len = 0;
    if (PBA_PROTOCOL == m_protocol)
		len = sizeof(PBAHead);

	return len;
}

int CCPackete::GetContentLength(void)
{
	int len = m_cache.data_len();
	len -= GetHeadLength();

	return len;
}

BYTE CCPackete::GetcbCheckCode(void)
{
    PBAHead* phead = (PBAHead*)m_cache.data();

	BYTE code = 0;
    if (PBA_PROTOCOL == m_protocol)
		code = phead->m_crc;
	return code;
}

uint32 CCPackete::GetMsgType(void)
{
	uint32 msg_type = 0;

	return msg_type;
}
USHORT CCPackete::GetDstType(void)
{
    PBAHead* phead = (PBAHead*)m_cache.data();

	USHORT dst_type = 0;
    if (PBA_PROTOCOL == m_protocol)
		dst_type = ntohs(phead->m_dsttype);

	return dst_type;
}
uint32 CCPackete::GetDstSvid(void)
{
    PBAHead* phead = (PBAHead*)m_cache.data();

	uint32 dst_svid = 0;
    if (PBA_PROTOCOL == m_protocol)
		dst_svid = ntohl(phead->m_dstid);

	return dst_svid;
}
USHORT CCPackete::GetSrcType(void)
{
    PBAHead* phead = (PBAHead*)m_cache.data();

	USHORT src_type = 0;
    if (PBA_PROTOCOL == m_protocol)
		src_type = ntohs(phead->m_srctype);

	return src_type;
}
uint32 CCPackete::GetSrcSvid(void)
{
    PBAHead* phead = (PBAHead*)m_cache.data();

	uint32 src_svid = 0;
    if (PBA_PROTOCOL == m_protocol)
		src_svid = ntohl(phead->m_srcid);

	return src_svid;
}
void CCPackete::SetSrcSvid(unsigned int srcid)
{
	PBAHead* phead = (PBAHead*)m_cache.data();
	if (PBA_PROTOCOL == m_protocol)
		phead->m_srcid = htonl(srcid);

	return;
}
uint32 CCPackete::GetSeq(void)
{
    PBAHead* phead = (PBAHead*)m_cache.data();

	uint32 seq = 0;
    if (PBA_PROTOCOL == m_protocol)
		seq = ntohl(phead->m_seq);

	return seq;
}

void CCPackete::SetSeq(uint32 seq)
{
    PBAHead* phead = (PBAHead*)m_cache.data();
    if (PBA_PROTOCOL == m_protocol)
		phead->m_seq = htonl(seq);
}

uint32 CCPackete::Getbitflag(void)
{
	PBAHead* phead = (PBAHead*)m_cache.data();
	uint32 bitflag = 0;
	if (PBA_PROTOCOL == m_protocol)
		bitflag = ntohl(phead->m_bitflag);

	return bitflag;
}

uint32 CCPackete::GetFlowId(void)
{
	uint32 flow_id = 0;

	return flow_id;
}

uint32 CCPackete::GetModKey(void)
{
	uint32 mod_key = 0;

	return mod_key;
}

void CCPackete::WritecbCheckCode(BYTE nValue) 
{ 
    PBAHead* phead = (PBAHead*)m_cache.data();

    if (PBA_PROTOCOL == m_protocol)
	    phead->m_crc = nValue;
}

char* CCPackete::bodydata(void)
{
	PBAHead* phead = (PBAHead*)m_cache.data();
	if(packet_size() >= GetHeadLength())
	{
		if (PBA_PROTOCOL == m_protocol)
	        if(ntohl(phead->m_datalen) > 0)
		        return phead->m_data;
	}

	return NULL;
}
unsigned int CCPackete::bodylen(void)
{
	PBAHead* phead = (PBAHead*)m_cache.data();
	if(packet_size() >= GetHeadLength())
	{
		if (PBA_PROTOCOL == m_protocol)
		    return ntohl(phead->m_datalen);
	}

	return 0;
}

bool CCPackete::parsePb(::google::protobuf::Message* pb)
{
	if (!pb)
		return false;

	uint32 bitflag = Getbitflag();
	if (bitflag & 0x01)
		CEncryptDecrypt::DecryptBuffer1(this);

	return pb->ParseFromArray(bodydata(), bodylen());
}

bool CCPackete::getPbData(std::string& data)
{
	uint32 bitflag = Getbitflag();
	if (bitflag & 0x01)
		CEncryptDecrypt::DecryptBuffer1(this);
	data.assign(bodydata(), bodylen());
	return true;
}

bool CCPackete::IsWritecbCheckCode(void)
{ 
    return m_bIsEncrypted;
}

void CCPackete::SetCheckCodeFlag(BYTE value)
{
    m_bIsEncrypted = value;
}

void CCPackete::_end(bool encode)
{
    PBAHead* phead = (PBAHead*)m_cache.data();

	uint16 len = m_cache.data_len();
    if (PBA_PROTOCOL == m_protocol)
	    phead->m_datalen = htonl(len - sizeof(PBAHead));

	if(encode)
	{
		CEncryptDecrypt::EncryptBuffer1(this);
		if (PBA_PROTOCOL == m_protocol)
	        phead->m_bitflag = htonl(ntohl(phead->m_bitflag)|g_encodeflag);
	}
}
/////////////////////////////////////////////////////////////////////////////////

// ȡ��һ������
bool CCPackete::_Read(char *pOut, int nLen)
{
	if ((nLen + m_nBufPos) > packet_size() || (nLen + m_nBufPos) > PACKET_BUFFER_SIZE || nLen < 0)
	{
		log_error("Fatal Error , nLen:%d , m_nBufPos:%d, packet_size=%d, ", nLen, m_nBufPos, packet_size());
		return false;
	}
	//log_debug("read nLen:%d , m_nBufPos:%d, packet_size=%d, ", nLen, m_nBufPos, packet_size());
	memcpy(pOut, packet_buf() + m_nBufPos, nLen);
	m_nBufPos += nLen;
	//log_debug("read2 nLen:%d , m_nBufPos:%d, packet_size=%d, ", nLen, m_nBufPos, packet_size());
	return true;
}

//������
void CCPackete::_readundo(int nLen)
{
	m_nBufPos -= nLen;
}

//������ǰPOSλ�õ�BUFFERָ��
char *CCPackete::_readpoint(int nLen)
{//ע�ⷵ�ص���ָ�� ������ʹ��string
	if ((nLen + m_nBufPos) > packet_size() || nLen < 0){
		log_error("Fatal Error , nLen:%d , m_nBufPos:%d", nLen, m_nBufPos);
		return NULL;
	}

	char *p = (packet_buf() + m_nBufPos);
	m_nBufPos += nLen;
	return p;
}


// д��һ������
bool CCPackete::_Write(const char *pIn, int nLen)
{
	if (/*(packet_size() < 0) ||*/ ((nLen + packet_size()) > PACKET_BUFFER_SIZE) || nLen < 0){
		log_error("Fatal Error , nLen:%d , packet_size:%d", nLen, packet_size());
		return false;
	}

	m_cache.append(pIn, nLen);
	return true;
}


bool CCPackete::_writezero(void)
{
	if ((m_cache.data_len() + 1) > PACKET_BUFFER_SIZE)
		return false;

	BYTE ch = '\0';
	m_cache.append((char*)&ch, 1);
	return true;
}


int InputPacket::ReadInt(void)
{ //��������ʼ��
	int nValue = -1; 
	base::_Read((char*)&nValue, sizeof(int)); 
	return ntohl(nValue); 
} 

int64 InputPacket::ReadInt64(void)        
{ 
	int64 nValue = -1; 
	base::_Read((char*)&nValue, sizeof(int64)); 
	return ntohll(nValue); 
}


short InputPacket::ReadShort(void)    
{ 
	short nValue = -1; 
	base::_Read((char*)&nValue, sizeof(short)); 
	return ntohs(nValue); 
}

BYTE InputPacket::ReadByte(void)        
{ 
	BYTE nValue = -1; 
	base::_Read((char*)&nValue, sizeof(BYTE)); 
	return nValue; 
}

int InputPacket::ReadString(char *pOutString, int nMaxLen)
{
	int nLen = ReadInt();
	if (nLen < 0)
	{//��������ж�
		pOutString[0] = '\0';
		return -1;
	}
	if (nLen > nMaxLen)
	{
		base::_readundo(sizeof(uint32));
		return -1;
	}
	if (base::_Read(pOutString, nLen))
		return nLen;
	
	return -1;
}

char * InputPacket::ReadChar(void)
{
	int nLen = ReadInt();
	if (nLen < 0)
		return NULL;
	return base::_readpoint(nLen);
}

string InputPacket::ReadString(void)
{
	char *p = ReadChar();
	return (p == NULL ? "" : p);
}

int InputPacket::ReadBinary(char *pBuf, int nMaxLen)
{
	int nLen = ReadInt();
	if (nLen < 0)
	{
		return -1;
	}
	if (nLen > nMaxLen)
	{
		base::_readundo(sizeof(int));
		return -1;
	}
	if (base::_Read(pBuf, nLen))
		return nLen;
	return 0;
}

void InputPacket::Reset(void)
{
	base::_reset();
}

bool InputPacket::Copy(const void *pInBuf, int nLen)
{
	return base::_copy(pInBuf, nLen);
}


OutputPacket::OutputPacket()
{
}

OutputPacket::~OutputPacket()
{
}

bool OutputPacket::WriteInt(int nValue)        
{ 
	int value = htonl(nValue); 
	return base::_Write((char*)&value, sizeof(int)); 
}

bool OutputPacket::WriteInt64(int64 nValue)        
{ 
	int64 value = htonll(nValue); 
	return base::_Write((char*)&value, sizeof(int64)); 
}


bool OutputPacket::WriteByte(BYTE nValue)        
{ 
	return base::_Write((char*)&nValue, sizeof(BYTE)); 
}

bool OutputPacket::WriteShort(short nValue)    
{ 
	short value = htons(nValue); 
	return base::_Write((char*)&value, sizeof(short)); 
}

bool OutputPacket::WriteString(const char *pString)
{
	int nLen = (int)strlen(pString);
	WriteInt(nLen + 1);
	if (nLen > 0)
	{
		return base::_Write(pString, nLen) && base::_writezero();
	}
	else
	{
		return base::_writezero();
	}
}

bool OutputPacket::WriteString(const string &strDate)
{
	int nLen = (int)strDate.size();
	if (nLen > 0)
	{
		WriteInt(nLen + 1);
		return base::_Write(strDate.c_str(), nLen) && base::_writezero();
	}
	else
	{
		WriteInt(1);
		return base::_writezero();
	}
}

bool OutputPacket::WriteBinary(const char *pBuf, int nLen)
{
	if (nLen > 0)
	{
		WriteInt(nLen);
		return base::_Write(pBuf, nLen);
	}
	return false;
}

bool OutputPacket::WriteBP(const char *pBuf, unsigned int nLen)
{
	if(nLen > 0)
	    return base::_Write(pBuf, nLen);

	return false;
}

bool OutputPacket::Copy(const void *pInBuf, int nLen)
{
	return base::_copy(pInBuf, nLen);
}

void OutputPacket::Begin(uint32 nCmd, int proto_type)
{
	base::_begin(nCmd, proto_type);
}

void OutputPacket::Begin(unsigned int cmd, unsigned short dsttype, unsigned int dstid, unsigned short srctype, unsigned int srcid, unsigned int seq, int proto_type)
{
	base::_begin(cmd, dsttype, dstid, srctype, srcid, seq, proto_type);
}

void OutputPacket::End(bool encode)
{
	base::_end(encode);
}

NAMESPACE_CC_BY_END


